﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace ICodeShare.UI.Utils.Helpers
{
    public class ColorHelper
    {
        /// <summary>  
        /// 将blend的8位颜色值转为Color  
        /// </summary>  
        /// <param name="strColor"></param>  
        /// <returns></returns>  
        public Color strColorToColor(string strColor)
        {
            if (strColor.StartsWith("#"))
                strColor = strColor.Replace("#", string.Empty);
            int v = int.Parse(strColor, System.Globalization.NumberStyles.HexNumber);
            return new Color()
            {
                A = Convert.ToByte((v >> 24) & 255),
                R = Convert.ToByte((v >> 16) & 255),
                G = Convert.ToByte((v >> 8) & 255),
                B = Convert.ToByte((v >> 0) & 255)
            };
        }

        /// <summary>
        /// 将Color颜色转换成颜色字符串
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        public static string ColorToStringColor(Color color)
        {
            return color.A.ToString() + ',' + color.R.ToString() + ',' + color.G.ToString() + ',' + color.B.ToString();
        }

        /// <summary>
        /// 将颜色字符串转换成Color颜色
        /// </summary>
        /// <param name="strColor"></param>
        /// <returns></returns>
        /// <remarks>
        /// String类似于"255,255,255,0"
        /// </remarks>
        public static Color StringColorToColor(string strColor)
        {
            string[] color_params = strColor.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            byte color_A = Convert.ToByte(color_params[0]);
            byte color_R = Convert.ToByte(color_params[1]);
            byte color_G = Convert.ToByte(color_params[2]);
            byte color_B = Convert.ToByte(color_params[3]);
            if (color_params.Length != 4) return Colors.Black;
            else
            {
                return Color.FromArgb(color_A, color_R, color_G, color_B);
            }
        }

      

        /// <summary>
        /// 将Color颜色转换成Brush画刷
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        /// <remarks>
        /// 
        /// </remarks>
        public static Brush ColorToBrush(Color color)
        {
            Brush br = new SolidColorBrush(color);
            return br;
        }

        /// <summary>
        /// 判断字符串是否可转换成Color颜色
        /// </summary>
        /// <param name="strColor"></param>
        /// <returns></returns>
        /// <remarks>
        /// String类似于Black、Green、Red
        /// </remarks>
        public static bool CanConvertFromString(string strColor)
        {
            ColorConverter converter = new ColorConverter();
            return converter.IsValid(strColor);
        }

        /// <summary>
        /// 将字符串转化为Color颜色
        /// </summary>
        /// <param name="strColor"></param>
        /// <returns></returns>
        /// <remarks>
        /// String类似于Black、Green、Red
        /// </remarks>
        public static Color StringToColor(string strColor)
        {
            return (Color)ColorConverter.ConvertFromString(strColor);
        }


        /// <summary>
        /// 将字符串转化为Brush画刷
        /// </summary>
        /// <param name="strColor"></param>
        /// <returns></returns>
        /// <remarks>
        /// String类似于Black、Green、Red
        /// </remarks>
        public static Brush StringToBrush(string strColor)
        {
            ColorConverter c = new ColorConverter();

            Brush br = new SolidColorBrush((Color)ColorConverter.ConvertFromString((string)strColor));
            return br;
        }

        /// <summary>
        /// 将颜色Byte[]转化为颜色字符串
        /// </summary>
        /// <param name="strColor"></param>
        /// <returns></returns>
        /// <remarks>
        /// String类似于"255,0,255,0"
        /// </remarks>
        public static string ByteToStringColor(byte[] byteColor)
        {
            System.Text.UnicodeEncoding converter = new System.Text.UnicodeEncoding();
            string strColor = converter.GetString(byteColor);
            return strColor;
        }

        /// <summary>
        /// 将颜色字符串转化为颜色Byte[]
        /// </summary>
        /// <param name="strColor"></param>
        /// <returns></returns>
        /// <remarks>
        /// String类似于"255,0,255,0"
        /// </remarks>
        public static Byte[] StringColorToByte(string strColor)
        {
            System.Text.UnicodeEncoding converter = new System.Text.UnicodeEncoding();
            byte[] stringBytes = converter.GetBytes(strColor);
            return stringBytes;
        }

        #region Methods 方法
        /// <summary>
        /// 获取随机颜色
        /// </summary>
        /// <returns></returns>
        public static Color GetRandomColor()
        {
            Random random = new Random();
            return Color.FromRgb((byte)random.Next(0, 255), (byte)random.Next(0, 255), (byte)random.Next(0, 255));
        }

        /// <summary>
        /// 将Color颜色转换成相反Color颜色
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        public static Color ColorInvert(Color color)
        {
            return Color.FromArgb(255, (byte)(255 - color.R), (byte)(255 - color.G), (byte)(255 - color.B));
        }

        /// <summary>
        /// 从图像中获取像素点的颜色
        /// </summary>
        /// <param name="Source"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public static Color PickColor(BitmapSource Source, double x, double y)
        {
            if (Source == null)
                throw new InvalidOperationException("Image Source not set");

            BitmapSource bitmapSource = Source as BitmapSource;
            if (bitmapSource != null)
            { // Get color from bitmap pixel.
                // Convert coopdinates from WPF pixels to Bitmap pixels and restrict them by the Bitmap bounds.
                // x *= bitmapSource.PixelWidth / ActualWidth;
                if ((int)x > bitmapSource.PixelWidth - 1)
                    x = bitmapSource.PixelWidth - 1;
                else if (x < 1)
                    x = 1;
                //y *= bitmapSource.PixelHeight / ActualHeight;
                if ((int)y > bitmapSource.PixelHeight - 1)
                    y = bitmapSource.PixelHeight - 1;
                else if (y < 1)
                    y = 1;

                // Lee Brimelow approach (http://thewpfblog.com/?p=62).
                //byte[] pixels = new byte[4];
                //CroppedBitmap cb = new CroppedBitmap(bitmapSource, new Int32Rect((int)x, (int)y, 1, 1));
                //cb.CopyPixels(pixels, 4, 0);
                //return Color.FromArgb(pixels[3], pixels[2], pixels[1], pixels[0]);

                // Alternative approach
                if (bitmapSource.Format == PixelFormats.Indexed4)
                {
                    byte[] pixels = new byte[1];
                    int stride = (bitmapSource.PixelWidth * bitmapSource.Format.BitsPerPixel + 3) / 4;
                    bitmapSource.CopyPixels(new Int32Rect((int)x, (int)y, 1, 1), pixels, stride, 0);

                    Debug.Assert(bitmapSource.Palette != null, "bitmapSource.Palette != null");
                    Debug.Assert(bitmapSource.Palette.Colors.Count == 16, "bitmapSource.Palette.Colors.Count == 16");
                    return bitmapSource.Palette.Colors[pixels[0] >> 4];
                }
                else if (bitmapSource.Format == PixelFormats.Indexed8)
                {
                    byte[] pixels = new byte[1];
                    int stride = (bitmapSource.PixelWidth * bitmapSource.Format.BitsPerPixel + 7) / 8;
                    bitmapSource.CopyPixels(new Int32Rect((int)x, (int)y, 1, 1), pixels, stride, 0);

                    Debug.Assert(bitmapSource.Palette != null, "bitmapSource.Palette != null");
                    Debug.Assert(bitmapSource.Palette.Colors.Count == 256, "bitmapSource.Palette.Colors.Count == 256");
                    return bitmapSource.Palette.Colors[pixels[0]];
                }
                else
                {
                    byte[] pixels = new byte[4];
                    int stride = (bitmapSource.PixelWidth * bitmapSource.Format.BitsPerPixel + 7) / 8;
                    bitmapSource.CopyPixels(new Int32Rect((int)x, (int)y, 1, 1), pixels, stride, 0);

                    return Color.FromArgb(pixels[3], pixels[2], pixels[1], pixels[0]);
                }
                // TODO There are other PixelFormats which processing should be added if desired.
            }


            throw new InvalidOperationException("Unsupported Image Source Type");
        }

        /// <summary>
        /// 获取图像中像素点周围4x4最亮点或最暗点
        /// </summary>
        /// <param name="Source"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="IsDarkBack"></param>
        /// <returns></returns>
        public static Point PickPoint(BitmapSource Source, double x, double y, bool IsDarkBack)
        {
            if (Source == null)
                throw new InvalidOperationException("Image Source not set");

            BitmapSource bitmapSource = Source as BitmapSource;
            if (bitmapSource != null)
            {
                List<Point> lstPoint = new List<Point>();
                List<float> lstGray = new List<float>();
                int XAlix = (int)x;
                int YAlix = (int)y;
                for (int i = XAlix - 4; i <= XAlix + 4; i++)
                {
                    for (int j = YAlix - 4; j <= YAlix + 4; j++)
                    {
                        int ActureX = i;
                        int ActureY = j;
                        if ((int)ActureX > bitmapSource.PixelWidth - 1)
                            ActureX = bitmapSource.PixelWidth - 1;
                        else if (ActureY < 1)
                            ActureY = 1;

                        if ((int)ActureY > bitmapSource.PixelHeight - 1)
                            ActureY = bitmapSource.PixelHeight - 1;
                        else if (ActureY < 1)
                            ActureY = 1;

                        lstPoint.Add(new Point(ActureX, ActureY));
                        Color color = PickColor(Source, ActureX, ActureY);
                        lstGray.Add((float)(color.R * 0.3 + color.G * 0.59 + color.B * 0.11));
                    }
                }
                float MinGray = 0;
                float MaxGray = 0;
                int MinIndex = 0;
                int MaxIndex = 0;
                for (int m = 0; m < lstGray.Count - 1; m++)
                {
                    if (MinGray < lstGray[m])
                    {
                        MinGray = lstGray[m];
                        MinIndex = m;
                    }
                    if (MaxGray > lstGray[m])
                    {
                        MaxGray = lstGray[m];
                        MaxIndex = m;
                    }
                }
                if (IsDarkBack)
                {
                    return lstPoint[MinIndex];
                }
                else
                {
                    return lstPoint[MaxIndex];
                }

            }
            throw new InvalidOperationException("Unsupported Image Source Type");
        }

        #endregion
    }
}
